Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

63-9kyo-hwang #218

Merged
merged 6 commits into from
Sep 25, 2024
Merged

63-9kyo-hwang #218

merged 6 commits into from
Sep 25, 2024

Conversation

9kyo-hwang
Copy link
Collaborator

@9kyo-hwang 9kyo-hwang commented Sep 3, 2024

πŸ”— 문제 링크

ꡬ간 λ‚˜λˆ„κΈ° 2

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

1μ‹œκ°„ νŠΈλΌμ΄ν•˜κ³  레퍼런슀 확인

✨ μˆ˜λ„ μ½”λ“œ

1. 문제

N개의 수둜 이루어진 1차원 배열이 μžˆλ‹€. 이 배열을 M개 μ΄ν•˜μ˜ κ΅¬κ°„μœΌλ‘œ λ‚˜λˆ„μ–΄μ„œ κ΅¬κ°„μ˜ 점수의 μ΅œλŒ“κ°’μ„ μ΅œμ†Œλ‘œ ν•˜λ €κ³  ν•œλ‹€. ꡬ간은 λ‹€μŒκ³Ό 같은 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

  1. ν•˜λ‚˜μ˜ ꡬ간은 ν•˜λ‚˜ μ΄μƒμ˜ μ—°μ†λœ μˆ˜λ“€λ‘œ 이루어져 μžˆλ‹€.
  2. λ°°μ—΄μ˜ 각 μˆ˜λŠ” λͺ¨λ‘ ν•˜λ‚˜μ˜ ꡬ간에 ν¬ν•¨λ˜μ–΄ μžˆμ–΄μ•Ό ν•œλ‹€.

κ΅¬κ°„μ˜ μ μˆ˜λž€ ꡬ간에 μ†ν•œ 수의 μ΅œλŒ“κ°’κ³Ό μ΅œμ†Ÿκ°’μ˜ 차이이닀.

예λ₯Ό λ“€μ–΄, 배열이 [1, 5, 4, 6, 2, 1, 3, 7] 이고, M = 3인 κ²½μš°κ°€ μžˆλ‹€.

μ΄λ•Œ, [1, 5], [4, 6, 2], [1, 3, 7]둜 ꡬ간을 λ‚˜λˆ„λ©΄ 각 κ΅¬κ°„μ˜ μ μˆ˜λŠ” 4, 4, 6점이 λœλ‹€. μ΄λ•Œ, μ΅œλŒ“κ°’μ€ 6점이닀.

λ§Œμ•½, [1, 5, 4], [6, 2, 1], [3, 7]둜 ꡬ간을 λ‚˜λˆ„μ—ˆλ‹€λ©΄, 각 κ΅¬κ°„μ˜ μ μˆ˜λŠ” 4, 5, 4점이 되고, μ΄λ•Œ μ΅œλŒ“κ°’μ€ 5점이 λœλ‹€.

두 경우 μ€‘μ—μ„œ μ΅œλŒ“κ°’μ΄ μ΅œμ†ŒμΈ 것은 5점인 것이고, 5점보닀 μ΅œλŒ“κ°’μ„ μž‘κ²Œ λ§Œλ“œλŠ” 방법은 μ—†λ‹€.

λ°°μ—΄κ³Ό M이 μ£Όμ–΄μ‘Œμ„ λ•Œ, κ΅¬κ°„μ˜ 점수의 μ΅œλŒ“κ°’μ˜ μ΅œμ†Ÿκ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

2. 풀이

M개 μ΄ν•˜μ˜ κ΅¬κ°„μœΌλ‘œ 배열을 λ‚˜λˆ μ•Ό ν•˜λŠ”λ°, 이λ₯Ό λ¬΄μ‹ν•˜κ²Œ λ‹€ 닀루기엔 경우의 μˆ˜κ°€ λ„ˆλ¬΄ λ§Žλ‹€. λ‹¨μˆœνžˆ M이 μ΅œλŒ€ NκΉŒμ§€ 가기도 ν•˜κ³ , 심지어 M "μ΄ν•˜"이기 λ•Œλ¬Έμ— 경우의 μˆ˜λŠ” 폭발적으둜 λŠ˜μ–΄λ‚œλ‹€.

λ¬Έμ œμ—μ„œ κ΅¬ν•˜κ³ μž ν•˜λŠ” 건 ꡬ간 점수 μ΅œλŒ€κ°’ 쀑 μ΅œμ†Œκ°’μΈλ°, μ—¬κΈ°μ„œ ꡬ간 점수(ν•΄λ‹Ή κ΅¬κ°„μ˜ μ΅œλŒ€κ°’ - μ΅œμ†Œκ°’)에 μ£Όλͺ©ν•œλ‹€.

이 점수 차이λ₯Ό νƒμƒ‰μ˜ key둜 ν•˜μ—¬, "전체 배열을 M개 μ΄ν•˜λ‘œ λΆ„ν• ν•  수 μžˆλŠ”" 것듀 쀑 κ°€μž₯ μž‘μ€ 점수λ₯Ό ꡬ해내면 정닡이닀. 이 λ•Œ "이진 탐색"으둜 μˆ˜ν–‰ν•œλ‹€. 그러면 μ‹œκ°„ λ³΅μž‘λ„λŠ” $Nlog(N)$으둜 μΆ©λΆ„νžˆ ν•΄κ²° κ°€λŠ₯ν•˜λ‹€.

int N, M; cin >> N >> M;

vector<int> Nums(N);
for(int& Num : Nums)
{
    cin >> Num;
}

int Min = 0, Max = *max_element(Nums.begin(), Nums.end());
int Score = Max;

κ΅¬κ°„μ˜ 점수 μ°¨μ΄λŠ” μ΅œμ†Œ 0점(ꡬ간 λ‚΄ λͺ¨λ“  μˆ«μžκ°€ 동일함)λΆ€ν„° μ΅œλŒ€ 9999점(λ°°μ—΄μ˜ μˆ˜λŠ” μ΅œμ†Œ 1, μ΅œλŒ€ 10000)이닀. 이 λ²”μœ„ λ‚΄μ—μ„œ νƒ€κ²Ÿ 점수λ₯Ό μ°Ύμ•„λ³Έλ‹€. μ΄ˆκΈ°κ°’μ€ Max이닀.

while(Min <= Max)
{
    int EstimateScore = (Min + Max) / 2;
    if(IsValid(EstimateScore))
    {
        Score = min(Score, EstimateScore);
        Max = EstimateScore - 1;
    }
    else
    {
        Min = EstimateScore + 1;
    }
}

μ „ν˜•μ μΈ 이진탐색 λ‘œμ§μ΄λ‹€. IsValid() ν•¨μˆ˜μ˜ κ²°κ³Όκ°€ true이면 쑰건에 λΆ€ν•©ν•œ μΆ”μ • 점수라 이λ₯Ό minimum update μˆ˜ν–‰ν•œλ‹€.

auto IsValid = [&](int EstimateScore)
{
    int Count = 1;
    int Min = Nums[0], Max = Nums[0];
    
    for(int i = 1; i < N; ++i)
    {
        Min = min(Min, Nums[i]);
        Max = max(Max, Nums[i]);
        
        if(Max - Min > EstimateScore)
        {
            Count++;
            Min = Nums[i];
            Max = Nums[i];
        }
    }
    
    return Count <= M;
};

핡심 λ‘œμ§μ΄λ‹€. 예λ₯Ό λ“€μ–΄λ³΄μž: [1, 5, 4, 6, 2, 1, 3, 7], M = 3

  • EstimateScore == 3: ꡬ간은 [1, 5], [4, 6], [2, 1, 3], [7]둜 4개둜 M보닀 크기 λ•Œλ¬Έμ— 적정 μΆ”μ • μ μˆ˜κ°€ μ•„λ‹ˆλ‹€. / Min = 4(κ°±μ‹ ), Max = 7
  • EstimateScore == 5: ꡬ간은 [1, 5, 4, 6, 2, 1, 3], [7]둜 2κ°œμ΄λ―€λ‘œ 적정 μΆ”μ • μ μˆ˜μ΄λ‹€. -> min(Score, EstimateScore) = min(7, 5): 5 κ°±μ‹  / Min = 4, Max = 4(κ°±μ‹ )
  • EstimateScore == 4: ꡬ간은 [1, 5, 4], [6, 2], [1, 3], [7]둜 4κ°œμ΄λ―€λ‘œ 적정 μΆ”μ • μ μˆ˜κ°€ μ•„λ‹ˆλ‹€. / Min = 5, Max = 4
  • Min > Maxμ΄λ―€λ‘œ break

λ”°λΌμ„œ 정닡은 5이닀.

전체 μ½”λ“œ

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    
    int N, M; cin >> N >> M;
    
    vector<int> Nums(N);
    for(int& Num : Nums)
    {
        cin >> Num;
    }
    
    auto IsValid = [&](int EstimateScore)
    {
        int Count = 1;
        int Min = Nums[0], Max = Nums[0];
        
        for(int i = 1; i < N; ++i)
        {
            Min = min(Min, Nums[i]);
            Max = max(Max, Nums[i]);
            
            if(Max - Min > EstimateScore)
            {
                Count++;
                Min = Nums[i];
                Max = Nums[i];
            }
        }
        
        return Count <= M;
    };
    
    int Min = 0, Max = *max_element(Nums.begin(), Nums.end());
    int Score = Max;
    while(Min <= Max)
    {
        int EstimateScore = (Min + Max) / 2;
        if(IsValid(EstimateScore))
        {
            Score = min(Score, EstimateScore);
            Max = EstimateScore - 1;
        }
        else
        {
            Min = EstimateScore + 1;
        }
    }
    
    cout << Score;

    return 0;
}

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

이 λ¬Έμ œλŠ” 2024 NHN κ²Œμž„ 곡채 μ½”λ”© ν…ŒμŠ€νŠΈ λ¬Έμ œμ™€ μœ μ‚¬ν•˜λ‹€(λ””μŠ€μ½”λ“œμ— κ΄€λ ¨ ν¬μŠ€νŠΈκ°€ μžˆμœΌλ‹ˆ λ§Žκ΄€λΆ€!).

μ½”ν…Œ μΉ  λ‹Ήμ‹œμ—λŠ” μ–΄λ–€ μœ ν˜•μΈμ§€ νŒŒμ•…ν•˜μ§€ λͺ»ν•΄ λͺ» ν’€μ—ˆλŠ”λ° @mjj111 λ‹˜μ΄ "이거 μ΄μ§„νƒμƒ‰μž„!" ν•΄μ„œ λˆˆμ— λΆˆμ„ ν‚€κ³  λ°±μ€€ λ’€μ Έλ³΄λ‹ˆ λΉ„μŠ·ν•œ 게 이 λ¬Έμ œμ˜€λ‹€.

트라이 ν•΄λ΄€μ§€λ§Œ... 1μ‹œκ°„ λ™μ•ˆ 감도 λͺ»μž‘κ³  레퍼런슀 ν™•μΈν•˜κ³  λ‚˜μ„œμ•Ό 겨우겨우 끄적일 수 μžˆμ—ˆλ˜...

ν•œλ™μ•ˆ λ°±νŠΈλž˜ν‚Ή/이진탐색/그리디/DP μœ„μ£Όλ‘œ ν’€μ–΄μ•Όκ² λ‹€.

p.s. 참고둜 이 λ¬Έμ œλŠ” N의 크기가 μž‘μ–΄μ„œ λ‹€μŒκ³Ό 같이 μ„ ν˜• 탐색을 해도 ν†΅κ³Όν•œλ‹€.

int Score = 10001;
for(int EstimateScore = 0; EstimateScore < *max_element(Nums.begin(), Nums.end()); ++EstimateScore)
{
    if(IsValid(EstimateScore))
    {
        Score = min(Score, EstimateScore);
    }
}

image
(μœ„κ°€ μ„ ν˜•νƒμƒ‰, μ•„λž˜κ°€ 이진탐색)

Copy link
Collaborator

@mjj111 mjj111 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ§„μ§œ 이 문제λ₯Ό μ™œ... κ·Έ NHN μ‹œν—˜ λ•ŒλŠ” μ–΄λ²„λ²„λŒ”λŠ”μ§€.. ν™”κ°€ λ‚˜λŠ”κ΅°μš”..

n, m = map(int, input().split())
numbers = list(map(int, input().split()))
start = 0
end = max(numbers) - min(numbers)

def can_do(target):
    m_count = 1 
    min_value = numbers[0]
    max_value = numbers[0]
    
    for number in numbers[1:]:
        min_value = min(min_value, number)
        max_value = max(max_value, number)
        
        if max_value - min_value > target:
            m_count += 1  
            min_value = number 
            max_value = number
            
            if m_count > m:
                return False
    return True

while start <= end:
    mid = (start + end) // 2
    if can_do(mid):
        end = mid - 1
    else:
        start = mid + 1

print(start)

Copy link
Member

@gjsk132 gjsk132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이진 탐색인걸 μ•Œκ³  풀어도 뭔지 λ„μ €νžˆ λͺ¨λ₯΄κ² μ–΄μ„œ ꡬ간 λ‚˜λˆ„κΈ° 1 ν•΄κ²°ν•˜κ³  와야지 ν–ˆλ‹€κ°€....
κ·Έ λ¬Έμ œλŠ” DPλΌμ„œ κ·Έμ € μ‹œκ°„λ§Œ νŽ‘νŽ‘ λ‚ λ ΈμŠ΅λ‹ˆλ‹€...πŸ₯²

점수 차이λ₯Ό μ΄μš©ν•΄μ„œ 이진 탐색을 ν•˜λŠ”κ±΄ μ „ν˜€ 생각 λͺ»ν•œ λ°©λ²•μ΄λ„€μš”πŸ‘€

Copy link
Member

@xxubin04 xxubin04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문제λ₯Ό μ΅œλŒ€ν•œ 이해해보렀고 λ…Έλ ₯ν–ˆμœΌλ‚˜ λ„ˆλ¬΄ μ–΄λ ΅λ„€μš”..😭
μ΄μ§„νƒμƒ‰μœΌλ‘œ ν’€ 수 μžˆλ‹€κ³€ 생각 λͺ»ν–ˆλŠ”데 μ΄μ§„νƒμƒ‰μœΌλ‘œ ν’€λ¦¬λ‹€λ‹ˆ μ§„μ§œ μ•Œκ³ λ¦¬μ¦˜ λ„ˆλ¬΄ μ–΄λ €μ›Œμš”..!!
수고 λ§ŽμœΌμ…¨μŠ΅λ‹ˆλ‹€πŸ‘πŸ»βœ¨

@9kyo-hwang 9kyo-hwang merged commit b10dce5 into main Sep 25, 2024
7 checks passed
@9kyo-hwang 9kyo-hwang deleted the 63-9kyo-hwang branch September 25, 2024 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants